package com.nuanshui.heatedloan.service.cms.security;

import java.io.IOException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.alibaba.dubbo.config.annotation.Reference;
import com.nuanshui.framework.security.MD5Util;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.dubbo.extension.DubboContextManager;
import com.nuanshui.heatedloan.userinfo.facade.UserQueryService;
import com.nuanshui.heatedloan.userinfo.facade.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.nuanshui.heatedloan.constant.TransactionManagerType;
import com.nuanshui.heatedloan.dao.cms.security.UserDao;
import com.nuanshui.heatedloan.dao.cms.security.securityDaoImpl;
import com.nuanshui.heatedloan.dao.userinfo.UserInfoDaoImpl;
import com.nuanshui.heatedloan.entity.cms.security.User;
import com.nuanshui.heatedloan.extension.shiro.ShiroDbRealm;
import com.nuanshui.heatedloan.extension.shiro.ShiroDbRealm.HashPassword;
import com.nuanshui.heatedloan.service.cms.BaseService;
import com.nuanshui.heatedloan.service.cms.ServiceException;
import com.nuanshui.heatedloan.util.StorageService;
import com.nuanshui.heatedloan.util.dwz.DwzPage;
import com.nuanshui.heatedloan.util.springdata.PageUtils;



/**
 * 用户的管理类
 */
@Service
@Transactional(readOnly = true,value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
public class AdminUserService extends BaseService<User, Long> implements InitializingBean {
	private static final Logger logger = LoggerFactory
			.getLogger(AdminUserService.class);

	@Autowired
	private UserDao userDao;
	
	@Autowired
	private securityDaoImpl securityDao;

	@Autowired
	private ShiroDbRealm shiroRealm;
	
	@Autowired
	private UserInfoDaoImpl userInfoDaoImpl;
	
	@Autowired
	private FrontUserService frontUserService;

	@Reference(url= GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserQueryService userQueryService;

	@Reference(url= GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserService userService;


	@Override
	public User get(final Long id) {

		return userDao.findOne(id);
	}

	@Override
	public List<User> findAll(final DwzPage page) {
		final Page<User> page2 = userDao
				.findAll(PageUtils.createPageable(page));
		PageUtils.injectPageProperties(page, page2);
		return page2.getContent();
	}

	/**
	 * 保存用户
	 */
	@Override
	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void save(final User user) throws ServiceException {
		if (userDao.findByUsername(user.getUsername()) != null) {
			throw new ServiceException("用户添加失败，登录名：" + user.getUsername()
					+ "已存在。");
		}

		if (userDao.findByRealname(user.getRealname()) != null) {
			throw new ServiceException("用户添加失败，真实名：" + user.getRealname()
					+ "已存在。");
		}

		// 设定安全的密码，使用passwordService提供的salt并经过1024次 sha-1 hash
		if (StringUtils.isNotBlank(user.getPlainPassword())
				&& (shiroRealm != null)) {
			final HashPassword hashPassword = shiroRealm.encrypt(user
					.getPlainPassword());
			user.setSalt(hashPassword.salt);
			user.setPassword(hashPassword.password);
		}
		userDao.save(user);
		shiroRealm.clearCachedAuthorizationInfo(user.getUsername());

		createUserByManageUser(user);
	}

	@Override
	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void update(final User user) {
		// 设定安全的密码，使用passwordService提供的salt并经过1024次 sha-1 hash
		if (StringUtils.isNotBlank(user.getPlainPassword())
				&& (shiroRealm != null)) {
			final HashPassword hashPassword = shiroRealm.encrypt(user
					.getPlainPassword());
			user.setSalt(hashPassword.salt);
			user.setPassword(hashPassword.password);
			user.setPassword(hashPassword.password);
		}

		userDao.save(user);
	}

	@PersistenceContext
	EntityManager em;

	/**
	 * 修改用户
	 */
	@Transactional(readOnly = false,value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void update(final User user, final MultipartFile photos) {
		// 设定安全的密码，使用passwordService提供的salt并经过1024次 sha-1 hash
		if (StringUtils.isNotBlank(user.getPlainPassword())
				&& (shiroRealm != null)) {
			final HashPassword hashPassword = shiroRealm.encrypt(user
					.getPlainPassword());
			user.setSalt(hashPassword.salt);
			user.setPassword(hashPassword.password);
		}
		// 文件上传处理
		if (!photos.isEmpty()) {
			try {
				final String path = StorageService.IMAGES.save(photos);
				user.setPhoto(path);
			} catch (final IOException e) {
				e.printStackTrace();
			}
		}
		em.clear();
		userDao.save(user);
		shiroRealm.clearCachedAuthorizationInfo(user.getUsername());
	}

	/**
	 * 删除用户
	 */
	@Override
	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void delete(final Long id) throws ServiceException {
		if (isSupervisor(id)) {
			logger.warn("操作员{}，尝试删除超级管理员用户", SecurityUtils.getSubject()
					.getPrincipal() + "。");
			throw new ServiceException("不能删除超级管理员用户。");
		}
		userDao.delete(id);
	}

	/**
	 * 根据名称拿到一个用户
	 */
	public User get(final String username) {
		return userDao.findByUsername(username);
	}

	/**
	 * 分页
	 */
	public List<User> find(final DwzPage page, final String name) {
		final org.springframework.data.domain.Page<User> pageUser = userDao
				.findByUsernameContaining(name, PageUtils.createPageable(page));
		PageUtils.injectPageProperties(page, pageUser);
		return pageUser.getContent();
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(final Long id) {
		return id == 1;
	}


	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void deleteRolesById(Long userId) {
		userInfoDaoImpl.deleteRolesById(userId);
	}

	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void insertRoles(Long userId,Integer roleId) {
		userInfoDaoImpl.insertRoles( userId, roleId);
		
	}

	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void updateRoles(Long userId, List<Integer> roleIds) {
		// 删除掉当前用户之前存在的所有的角色
		deleteRolesById(userId);
		// 插入新的角色
		for (Integer roleId : roleIds) {
			insertRoles(userId, roleId);
		}

	}
	
	
	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void deleteById(Long id){
		userDao.deleteById(id);
	}
	
	/**
	 * 根据手机号码，获取app端的用户，然后根据app端用户获取后端用户返回
	 * @author Gonzo
	 * @date 2017年1月12日下午7:18:27
	 * @param phone
	 * @return
	 * @since 1.0.0
	 */
	@Transactional(value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public User getFrontUserByPhone(String phone) {
		/**----- Modify By:zss ;Date:2017/5/2 16:20----**/
		//通过用户的联系方式获取前端用户信息
		com.nuanshui.heatedloan.userinfo.model.User frontUser = frontUserService.getFrontUserByPhone(phone);
		//通过前后端用户中间表关系，来获取后端用户信息
		User adminUser = securityDao.loadAdminUserByForntUserId(frontUser.getId());
		adminUser.setPassword(frontUser.getPassword());//将密码设置为前端的密码
		//后端用户nick数据要和前端用户nick相等，这里就不验证了，直接更新
		this.updateUserNick(adminUser.getId().toString(),frontUser.getNick());
		//将昵称改为前端昵称，就不在查询一次了
		adminUser.setNick(frontUser.getNick());
		return adminUser;
	}
	
	
	/**
	 * 获取app端的用户id，根据后端的用户查找中间表
	 * @author Gonzo
	 * @date 2017年1月12日下午8:12:55
	 * @param userId
	 * @return
	 * @since 1.0.0
	 */
	public Integer loadFrontUserIdByAdminUserId(long userId){
		return securityDao.loadFrontUserIdByAdminUserId(userId);
	}
	/**
	 * 创建一个默认的场馆管理员
	 * @author Gonzo
	 * @date 2017年1月12日下午7:19:10
	 * @param user
	 * @since 1.0.0
	 */
	@Transactional(readOnly = false, value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void createUserByManageUser(User user) {

		boolean bFlag=userService.add(user.getPhone(), MD5Util.md5(user.getPlainPassword()).toLowerCase(),user.getUsername());

		if(bFlag)
		{
			com.nuanshui.heatedloan.userinfo.model.User userItem=userQueryService.loadUserByPhone(user.getPhone());
			Long id = securityDao.createDefaultAdminUserByFrontUserId(user.getId(), userItem.getId());
			//创建权限一个默认的管理员权限
			insertRoles(id.longValue(), -1);
		}
	}

	/**
	 * 删除展馆管理员用户
	 * @author Gonzo
	 * @date 2017年1月12日下午4:54:55
	 * @since 1.0.0
	 */
	@Transactional(readOnly = false, value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void deleteAdminUserByFrontUserId(String frontUserid) {
		securityDao.updateUserStatusToDisAble(frontUserid);//将后端的用户删除，这里只能删除，应为再次添加，loginname是不允许重复的
		securityDao.deleteAdminUserByFrontUserId(frontUserid);//将中间表删除
	}
	
	/**
	 * 更新用户别名
	 * @author zss
	 * @date 2017年4月28日下午12:54:55
	 * @param id
	 * @param nick
	 * @since 1.0.0
	 */
	@Transactional(readOnly = false, value=TransactionManagerType.MANAGER_SERVICE_TRANSACTION_MARGER)
	public void updateUserNick(String id,String nick) {
		securityDao.updateUserNick(id, nick);
	}

	@Override
	public void afterPropertiesSet() throws Exception {

		if(userQueryService==null)
		{
			userQueryService=DubboContextManager.getDubboBean(UserQueryService.class,GlobalParam.USER_DUBBO_SERVER_VERSION);
		}
		if(userService==null)
		{
			userService=DubboContextManager.getDubboBean(UserService.class,GlobalParam.USER_DUBBO_SERVER_VERSION);
		}

	}
}
